package co.yixiang.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ShareCodeUtils {


	private static final int offset = 24;
	private static final String stopChar = "Z";
	private static final int minCodeLen = 5;

	private static final Map<Integer, String> codeMap = new HashMap<Integer, String>() {
		private static final long serialVersionUID = 8079608538849685645L;

		{
		put(0, "A");
		put(1, "B");
		put(2, "C");
		put(3, "D");
		put(4, "E");
		put(5, "F");
		put(6, "G");
		put(7, "H");
		put(8, "I");
		put(9, "J");
		put(10, "K");
		put(11, "L");
		put(12, "M");
		put(13, "N");
		put(14, "P");
		put(15, "Q");
		put(16, "R");
		put(17, "S");
		put(18, "T");
		put(19, "U");
		put(20, "V");
		put(21, "W");
		put(22, "X");
		put(23, "Y");
	}};

	private static final Map<String, Integer> intMap = new HashMap<String, Integer>() {

		private static final long serialVersionUID = -2155582790030838660L;

		{
		put("A", 0);
		put("B", 1);
		put("C", 2);
		put("D", 3);
		put("E", 4);
		put("F", 5);
		put("G", 6);
		put("H", 7);
		put("I", 8);
		put("J", 9);
		put("K", 10);
		put("L", 11);
		put("M", 12);
		put("N", 13);
		put("P", 14);
		put("Q", 15);
		put("R", 16);
		put("S", 17);
		put("T", 18);
		put("U", 19);
		put("V", 20);
		put("W", 21);
		put("X", 22);
		put("Y", 23);
	}};

	/**
	 * 根据 id 生成邀请码 6 位
	 * 如果是 6 位的邀请码只能支持 191102976 1亿9千万用户
	 *
	 * @param id 用户id
	 * @return 邀请码
	 */
	public static String createCode(int id) {
		String code = int2chars(id);
		if (code.length() < (minCodeLen - 1)) {
			code = code + stopChar + codeTail(code);
		} else if (code.length() < minCodeLen) {
			code = code + stopChar;
		}
		return code;
	}

	/**
	 * 从邀请获取用户 id
	 *
	 * @param code 邀请码
	 * @return 用户id
	 */
	public static int codeRecover(String code) {
		int len = code.indexOf(stopChar);
		if (len > 0) {
			code = code.substring(0, len);
		}
		return chars2int(code);
	}

	private static String codeTail(String code) {
		StringBuilder res = new StringBuilder();
		String lastChar = code.substring(code.length() - 1);// 原code的尾数
		for (int i = 0; i < (minCodeLen - 1 - code.length()); i++) {
			res.append(lastChar);
		}
		return res.toString();
	}


	private static String int2chars(int id) {
		int div = id / offset;
		int remainder = id % offset;

		if (div == 0) {
			return codeMap.get(id);
		} else if (div < offset) {
			return codeMap.get(div) + codeMap.get(remainder);
		} else {
			return int2chars(div) + codeMap.get(remainder);
		}
	}

	private static int chars2int(String chats) {
		int res = 0;
		int codeLen = chats.length();
		for (int i = 0; i < codeLen; i++) {
			String a = chats.substring(i, i + 1);
			if (intMap.containsKey(a)) {
				res += intMap.get(a) * (Math.pow(offset, (codeLen - i - 1)));
			} else {
				res = 0;
				break;
			}
		}
		return res;
	}


	/** 自定义进制(0,1没有加入,容易与o,l混淆) */
	private static final char[] r=new char[]{'Q', 'W', 'E', '8', 'A', 'S', '2', 'D', 'Z', 'X', '9', 'C', '7', 'P', '5', 'I', 'K', '3', 'M', 'J', 'U', 'F', 'R', '4', 'V', 'Y', 'L', 'T', 'N', '6', 'B', 'G', 'H'};

	/** (不能与自定义进制有重复) */
	private static final char b='O';

	/** 进制长度 */
	private static final int binLen=r.length;

	/** 序列最小长度 */
	private static final int s=6;

	/**
	 * 根据ID生成六位随机码
	 * @param id ID
	 * @return 随机码
	 */
	public static String randomSerialCode(int id) {
		char[] buf=new char[32];
		int charPos=32;

		while((id / binLen) > 0) {
			int ind=(int)(id % binLen);
			// System.out.println(num + "-->" + ind);
			buf[--charPos]=r[ind];
			id /= binLen;
		}
		buf[--charPos]=r[(int)(id % binLen)];
		// System.out.println(num + "-->" + num % binLen);
		String str=new String(buf, charPos, (32 - charPos));
		// 不够长度的自动随机补全
		if(str.length() < s) {
			StringBuilder sb=new StringBuilder();
			sb.append(b);
			Random rnd=new Random();
			for(int i=1; i < s - str.length(); i++) {
				sb.append(r[rnd.nextInt(binLen)]);
			}
			str+=sb.toString();
		}
		return str;
	}

	public static int randomCodeToId(String code) {
		char[] chs =code.toCharArray();
		int res=0;
		for(int i=0; i < chs.length; i++) {
			int ind=0;
			for(int j=0; j < binLen; j++) {
				if(chs[i] == r[j]) {
					ind=j;
					break;
				}
			}
			if(chs[i] == b) {
				break;
			}
			if(i > 0) {
				res=res * binLen + ind;
			} else {
				res=ind;
			}
			// System.out.println(ind + "-->" + res);
		}
		return res;
	}
}
